package com.sxz.mall.mallseckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.sxz.mall.common.constant.SeckillConstant;
import com.sxz.mall.common.utils.R;
import com.sxz.mall.mallseckill.dto.SeckillSkuRedisDto;
import com.sxz.mall.mallseckill.feign.CouponFeignService;
import com.sxz.mall.mallseckill.feign.ProductFeignService;
import com.sxz.mall.mallseckill.service.SeckillService;
import com.sxz.mall.mallseckill.vo.SeckillSessionEntity;
import com.sxz.mall.mallseckill.vo.SeckillSkuRelationEntity;
import com.sxz.mall.mallseckill.vo.SkuInfoVo;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired //需要单独用@Configuration
    private RedissonClient redissonClient;

    @Autowired
    private ProductFeignService productFeignService;

    @Override
    public void uploadSeckillSku3Days() {
        // 远程调用feign
        R r = couponFeignService.getLatests3DaysSession();
//        List<SeckillSessionEntity> list = (List<SeckillSessionEntity>) r.get("data");
        List<SeckillSessionEntity> list = JSON.parseArray((String) r.get("data"),
                SeckillSessionEntity.class);

        // redis 数据保存  1、存储skuIds
        saveSessionInfos(list);

        // 2、存储各个商品详情  skuId--dto  skuInfo
        saveSessionSkuInfos(list);

    }

    private void saveSessionSkuInfos(List<SeckillSessionEntity> list) {
        for (SeckillSessionEntity seckillSessionEntity : list) {
            BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.
                    boundHashOps(SeckillConstant.SKU_CHACE_PREFIX);
            List<SeckillSkuRelationEntity> relationEntities = seckillSessionEntity.getRelationEntities();
            for (SeckillSkuRelationEntity relationEntity : relationEntities) {
                SeckillSkuRedisDto dto = new SeckillSkuRedisDto();
                BeanUtils.copyProperties(relationEntity, dto);

                // 设置秒杀时间
                dto.setStartTime(seckillSessionEntity.getStartTime().getTime());
                dto.setEndTime(seckillSessionEntity.getEndTime().getTime());

                // 设置随机码，保证公平性
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                dto.setRandCode(uuid);
                // 设置每件商品的信号量，限流用
                RSemaphore semaphore = redissonClient.getSemaphore(SeckillConstant.SKU_STOCK_SEMAPHORE + uuid);
                semaphore.trySetPermits(relationEntity.getSeckillCount().intValue());

                R info = productFeignService.info(relationEntity.getSkuId());
                if (info.getCode() == 0) {
                    SkuInfoVo skuInfo = (SkuInfoVo) info.get("skuInfo");
                    dto.setSkuInfoVo(skuInfo);
                }
                hashOperations.put(relationEntity.getSkuId().toString(),
                        JSON.toJSONString(dto));
            }
        }
    }

    private void saveSessionInfos(List<SeckillSessionEntity> list) {
        for (SeckillSessionEntity seckillSessionEntity : list) {
            long start = seckillSessionEntity.getStartTime().getTime();
            long end = seckillSessionEntity.getEndTime().getTime();
            String key = SeckillConstant.SESSION_CHACE_PREFIX + start + "_" + end;
            // redis中key是秒杀时间  value是所有商品id  skuIds
            List<String> skuIds = seckillSessionEntity.getRelationEntities().stream().
                    map((item) -> item.getSkuId().toString()).collect(Collectors.toList());
            stringRedisTemplate.opsForList().leftPushAll(key, skuIds);
        }
    }
}
